package cn.taobaoke.restful.datasource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author yangzuo
 * @since 2017-05-06 06:44
 */
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    @Override
    public void setEnvironment(Environment environment) {
        initDefaultDataSource(environment);
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("dataSource", defaultDataSource);
        DynamicDataSourceContextHolder.dataSourceMap.put("dataSource", "dataSource");

        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(DynamicDataSource.class);
        beanDefinition.setSynthetic(true);
        MutablePropertyValues mutablePropertyValues = beanDefinition.getPropertyValues();
        mutablePropertyValues.add("defaultTargetDataSource", defaultDataSource);
        mutablePropertyValues.add("targetDataSources", targetDataSources);
        beanDefinitionRegistry.registerBeanDefinition("dataSource", beanDefinition);
    }

    private void initDefaultDataSource(Environment environment) {
//        RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "spring.datasource.");

        HikariConfig config = new HikariConfig();

        config.setDriverClassName(environment.getProperty("spring.datasource.driver-class-name"));
        config.setJdbcUrl(environment.getProperty("spring.datasource.url"));
        config.setUsername(environment.getProperty("spring.datasource.username"));
        config.setPassword(environment.getProperty("spring.datasource.password"));
        config.setPoolName("HikariPool-Default");

        Optional<Object> poolSizeOpt = Optional.ofNullable(environment.getProperty("spring.datasource.hikari.maximum-pool-size"));
        Optional<Object> minIdleOpt = Optional.ofNullable(environment.getProperty("spring.datasource.hikari.minimum-idle"));
        Optional<Object> maxLifetimeOpt = Optional.ofNullable(environment.getProperty("spring.datasource.hikari.max-lifetime"));

        int poolSize = Integer.parseInt(poolSizeOpt.orElse("10").toString());
        int minIdle = Integer.parseInt(minIdleOpt.orElse("10").toString());
        int maxLifetime = Integer.parseInt(maxLifetimeOpt.orElse("1800000").toString());

        config.setMaximumPoolSize(poolSize);
        config.setMinimumIdle(minIdle);
        config.setMaxLifetime(maxLifetime);

        defaultDataSource = new HikariDataSource(config);
    }

    private DataSource defaultDataSource;
}
